package com.xusheng.cli.controller.open;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.*;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xusheng.cli.common.base.MyPage;
import com.xusheng.cli.common.base.Result;
import com.xusheng.cli.common.tools.QRCodeUtil;
import com.xusheng.cli.common.validation.Save;
import com.xusheng.cli.common.validation.Update;
import com.xusheng.cli.entity.backAgentModule.BackAgent;
import com.xusheng.cli.entity.frontUserModule.FrontUser;
import com.xusheng.cli.entity.frontUserModule.VipConfig;
import com.xusheng.cli.entity.paymentChannelModule.PaymentChannel;
import com.xusheng.cli.entity.rechargeModule.Recharge;
import com.xusheng.cli.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Size;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 充值表(Recharge)表控制层
 *
 * @author 王鹤然
 * @since 2023-07-03 12:38:12
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/open/v1/recharge")
public class RechargeController {

    private byte[] secretKey = KeyUtil.generateKey(SM4.ALGORITHM_NAME).getEncoded();
    private SymmetricCrypto sm4 = SmUtil.sm4(secretKey);

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Value("${server.port}")
    private int port;
    /**
     * 服务对象
     */
    @Resource
    private RechargeService rechargeService;
    @Resource
    private FrontUserService frontUserService;
    @Resource
    private VipConfigService vipConfigService;
    @Resource
    private PayService payService;
    @Resource
    private YzfPayService yzfPayService;
    @Resource
    private BackAgentService backAgentService;

    @Resource
    private PaymentChannelService paymentChannelService;


    /**
     * 查询所有数据
     *
     * @param recharge 查询实体
     * @return 所有数据
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @GetMapping("queryAll")
    public Result<List<Recharge>> queryAll(Recharge recharge) {
        return Result.success(rechargeService.list(new QueryWrapper<>(recharge)));
    }

    /**
     * 分页查询所有数据
     *
     * @param page     分页对象
     * @param recharge 查询实体
     * @return 所有数据
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @GetMapping("queryByPage")
    public Result<MyPage<Recharge>> queryByPage(MyPage<Recharge> page, Recharge recharge) {
        return Result.success(rechargeService.page(page, new QueryWrapper<>(recharge)));
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @GetMapping("queryOne/{id}")
    public Result<Recharge> selectOne(@PathVariable Serializable id) {
        return Result.success(rechargeService.getById(id));
    }

    /**
     * 新增数据
     *
     * @param recharge 实体对象
     * @return 新增结果
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @PostMapping("insert")
    public Result<Object> insert(@Validated(Save.class) @RequestBody Recharge recharge) {
        return Result.isSuccess(rechargeService.save(recharge));
    }

    /**
     * 修改数据
     *
     * @param recharge 实体对象
     * @return 修改结果
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @PutMapping("update")
    public Result<Object> update(@Validated(Update.class) @RequestBody Recharge recharge) {
        return Result.isSuccess(rechargeService.updateById(recharge));
    }

    /**
     * 删除单条数据
     *
     * @param id 主键
     * @return 删除结果
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @DeleteMapping("delete/{id}")
    public Result<Object> delete(@PathVariable Long id) {
        Recharge recharge = new Recharge();
        recharge.setId(id);
        return Result.isSuccess(rechargeService.removeById(recharge));
    }

    /**
     * 批量删除数据
     *
     * @param idList 主键结合
     * @return 删除结果
     * @author 王鹤然
     * @since 2023-07-03 12:38:12
     */
    @DeleteMapping("batchDelete")
    public Result<Object> batchDelete(@Validated @Size(min = 1, message = "缺少删除所需的id") @RequestParam("idList") List<Long> idList) {
        return Result.isSuccess(rechargeService.batchDelete(idList, new Recharge()));
    }

    /**
     * 根据 content 生成二维码
     *
     * @return
     */
    @GetMapping("/getQRCodeBase64")
    public Result<Object> getQRCode(HttpServletRequest request, Long vipId, Long paymentId, Long userId) {
        String returnUrl = request.getScheme() + "://" + request.getServerName();
        String orderId = IdUtil.getSnowflake().nextIdStr();
        String params = "{v:" + vipId + ",p:" + paymentId + ",u:" + userId + ",o:" + orderId + "}";
        String encryptHex = sm4.encryptHex(params);
        byte[] zlib = ZipUtil.zlib(encryptHex, "utf-8", 9);
        String s = HexUtil.encodeHexStr(zlib);
        log.info("加密后的结果：{}", s);
        byte[] bytes = HexUtil.decodeHex(s);
        String s1 = ZipUtil.unZlib(bytes, "utf-8");
        log.info("压缩后的结果：{}", s1);
        String content = returnUrl + contextPath + "/open/v1/recharge/payReturn?req=" + s1;
        log.info("二维码内容：{}", content);
        Map<String, Object> map = new HashMap<>();
        map.put("qrcode", QRCodeUtil.getBase64QRCode(content));
        map.put("orderId", orderId);
        return Result.success(map);
    }

    /**
     * 根据 content 生成二维码
     */
    @GetMapping(value = "/getQRCode")
    public void getQRCode(HttpServletRequest request, HttpServletResponse response, Long vipId, Long paymentId, Long userId, Long orderId) throws Exception {
        String returnUrl = request.getScheme() + "://" + request.getServerName();
        String params = "{v:" + vipId + ",p:" + paymentId + ",u:" + userId + ",o:" + orderId + "}";
        String encryptHex = sm4.encryptHex(params);
        byte[] zlib = ZipUtil.zlib(encryptHex, "utf-8", 9);
        String s = HexUtil.encodeHexStr(zlib);
        log.info("加密后的结果：{}", s);
        byte[] bytes = HexUtil.decodeHex(s);
        String s1 = ZipUtil.unZlib(bytes, "utf-8");
        log.info("压缩后的结果：{}", s1);
        String content = returnUrl + contextPath + "/open/v1/recharge/payReturn?req=" + s1;
        log.info("二维码内容：{}", content);
        ServletOutputStream stream = null;
        try {
            stream = response.getOutputStream();
            QRCodeUtil.getQRCode(content, stream);
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            if (stream != null) {
                stream.flush();
                stream.close();
            }
        }
    }

    @GetMapping("payReturn")
    public void payReturn(@RequestParam String req, HttpServletRequest request, HttpServletResponse response) throws IOException {

        SymmetricCrypto sm41 = SmUtil.sm4(secretKey);
        String decryptStr = sm41.decryptStr(req, CharsetUtil.CHARSET_UTF_8);
        JSONObject obj = JSONUtil.parseObj(decryptStr);
        log.info("obj->{}", obj);
        Long orderId = obj.getLong("o");
        Long vipId = obj.getLong("v");
        Long paymentId = obj.getLong("p");
        Long userId = obj.getLong("u");
        // 获取用户信息
        FrontUser frontUser = frontUserService.getById(userId);
        // 获取支付通道信息
        PaymentChannel paymentChannel = paymentChannelService.getById(paymentId);
        // 获取会员信息
        VipConfig vipConfig = vipConfigService.getById(vipId);
        String qrCode;
        // 获取未支付订单
        Recharge order = rechargeService.getOne(new QueryWrapper<>(new Recharge()).lambda().eq(Recharge::getId, orderId).eq(Recharge::getPayInfo, false));
        if (order == null) {
            // 创建订单
            order = new Recharge();
            order.setId(orderId);
            order.setIdPrefix(DateUtil.format(new Date(), "yyyyMMdd"));
            order.setOrderNumber(order.getIdPrefix() + order.getId());
            order.setPlayerId(obj.getLong("u"));
            order.setPlayerAccount(frontUser.getAccount());
            order.setPayMode(paymentChannel.getType().getCode());
            order.setRechargeAmount(vipConfig.getAmount());
            order.setPaymentId(paymentId);
            order.setVipId(vipId);
            order.setPayInfo(false);
            order = mathIncome(order, frontUser);
            rechargeService.save(order);
            // 调取发卡支付接口
            qrCode = payService.createOrder(order, request);
            // 更新二维码地址
            order.setQrCode(qrCode);
            rechargeService.updateById(order);
        } else if (StrUtil.isBlank(order.getQrCode())) {
            // 调取发卡支付接口
            qrCode = payService.createOrder(order, request);
            // 更新二维码地址
            order.setQrCode(qrCode);
            rechargeService.updateById(order);
        } else {
            qrCode = order.getQrCode();
        }
        // 重定向
        response.sendRedirect(qrCode);
    }

    @GetMapping("yzfPayReturn")
    public Result<Object> yzfPayReturn(Long vipId, Long paymentId, Long userId, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取用户信息
        FrontUser frontUser = frontUserService.getById(userId);
        // 获取支付通道信息
        PaymentChannel paymentChannel = paymentChannelService.getById(paymentId);
        // 获取会员信息
        VipConfig vipConfig = vipConfigService.getById(vipId);
        String qrCode;

        // 创建订单
        Recharge order = new Recharge();
        order.setIdPrefix(DateUtil.format(new Date(), "yyyyMMdd"));
        order.setOrderNumber(order.getIdPrefix() + System.currentTimeMillis() / 1000);
        order.setPlayerId(userId);
        order.setPlayerAccount(frontUser.getAccount());
        order.setPayMode(paymentChannel.getType().getCode());
        order.setRechargeAmount(vipConfig.getAmount());
        order.setPaymentId(paymentId);
        order.setVipId(vipId);
        order.setPayInfo(false);
        order = mathIncome(order, frontUser);
        rechargeService.save(order);
        // 调取发卡支付接口
        qrCode = yzfPayService.createOrder(order, request);
        // 更新二维码地址
        order.setQrCode(qrCode);
        rechargeService.updateById(order);

        Map<String, Object> map = new HashMap<>();
        log.info("支付方式：{}", paymentChannel.getType());
        if (paymentChannel.getChannel() == 1 && "alipay".equals(paymentChannel.getType().getKey())) {
            map.put("qrcode", qrCode);
        } else {
            map.put("qrcode", QRCodeUtil.getBase64QRCode(qrCode));
        }
        map.put("type", paymentChannel.getType().getKey());
        map.put("orderId", order.getId());
        return Result.success(map);
    }

    @GetMapping("payReturnApp")
    public Result<Object> payReturn(Long vipId, Long paymentId, Long userId, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取用户信息
        FrontUser frontUser = frontUserService.getById(userId);
        // 获取支付通道信息
        PaymentChannel paymentChannel = paymentChannelService.getById(paymentId);
        // 获取会员信息
        VipConfig vipConfig = vipConfigService.getById(vipId);
        String qrCode;
        Long orderId = IdUtil.getSnowflake().nextId();
        // 获取未支付订单
        Recharge order = rechargeService.getOne(new QueryWrapper<>(new Recharge()).lambda().eq(Recharge::getId, orderId).eq(Recharge::getPayInfo, false));
        if (order == null) {
            // 创建订单
            order = new Recharge();
            order.setId(orderId);
            order.setIdPrefix(DateUtil.format(new Date(), "yyyyMMdd"));
            order.setOrderNumber(order.getIdPrefix() + order.getId());
            order.setPlayerId(userId);
            order.setPlayerAccount(frontUser.getAccount());
            order.setPayMode(paymentChannel.getType().getCode());
            order.setRechargeAmount(vipConfig.getAmount());
            order.setPaymentId(paymentId);
            order.setVipId(vipId);
            order.setPayInfo(false);
            order = mathIncome(order, frontUser);
            rechargeService.save(order);
            // 调取发卡支付接口
            qrCode = payService.createOrder(order, request);
            // 更新二维码地址
            order.setQrCode(qrCode);
            rechargeService.updateById(order);
        } else if (StrUtil.isBlank(order.getQrCode())) {
            // 调取发卡支付接口
            qrCode = payService.createOrder(order, request);
            // 更新二维码地址
            order.setQrCode(qrCode);
            rechargeService.updateById(order);
        } else {
            qrCode = order.getQrCode();
        }
        // 重定向
//        response.sendRedirect(qrCode);
        Map<String, Object> map = new HashMap<>();
        map.put("qrCode", qrCode);
        map.put("orderId", orderId);
        return Result.success(map);
    }

    /**
     * 查询订单状态是否已完成
     *
     * @param id
     * @return
     */
    @GetMapping("getOrderStatus/{id}")
    public Result<Boolean> getOrderStatus(@PathVariable Serializable id) {
        Recharge order = rechargeService.getOne(new QueryWrapper<>(new Recharge()).lambda().eq(Recharge::getId, id).eq(Recharge::getPayInfo, true));
        return Result.success(order != null);
    }

    /**
     * 会员兑换
     *
     * @param obj
     * @return
     */
    @Transactional
    @PostMapping("exchange")
    public Result<Object> vipExchange(@RequestBody Map<String, Object> obj) {
        Long vipId = Long.parseLong(obj.get("vipId").toString());
        Long userId = Long.parseLong(obj.get("userId").toString());
        // 获取用户信息
        FrontUser frontUser = frontUserService.getById(userId);
        // 获取会员信息
        VipConfig vipConfig = vipConfigService.getById(vipId);
        if (vipConfig.getRechargeType() == 3) {
            // 金币
            if (frontUser.getGold() < vipConfig.getAmount().intValue()) {
                return Result.error("金币不足，无法兑换");
            }
            frontUser.setGold(frontUser.getGold() - vipConfig.getAmount().intValue());
            LocalDateTime vipExpires;
            // 会员到期时间
            if (frontUser.getVipExpires() == null || frontUser.getVipExpires().isBefore(LocalDateTime.now())) {
                vipExpires = LocalDateTime.now();
            } else {
                vipExpires = frontUser.getVipExpires();
            }
            if (vipConfig.getType() == 0) {
                // 添加次数
                frontUser.setWatchCount(frontUser.getWatchCount() + 1);
            } else if (vipConfig.getType() == 1) {
                // 添加天数
                frontUser.setVipExpires(vipExpires.plusDays(vipConfig.getDays() + vipConfig.getPresent()));
                frontUser.setVipId(vipConfig.getId());
            } else if (vipConfig.getType() == 2) {
                // 添加月数
                frontUser.setVipExpires(vipExpires.plusMonths(vipConfig.getDays()).plusDays(vipConfig.getPresent()));
                frontUser.setVipId(vipConfig.getId());
            }

            // 创建订单
            Recharge order = new Recharge();
            order.setId(IdUtil.getSnowflake().nextId());
            order.setIdPrefix(DateUtil.format(new Date(), "yyyyMMdd"));
            order.setOrderNumber(order.getIdPrefix() + order.getId());
            order.setPlayerId(userId);
            order.setPlayerAccount(frontUser.getAccount());
            order.setRechargeAmount(vipConfig.getAmount());
            order.setVipId(vipId);
            order.setPayInfo(true);
            rechargeService.save(order);
        }
        return Result.isSuccess(frontUserService.updateById(frontUser));
    }

    public Recharge mathIncome(Recharge recharge, FrontUser frontUser) {
        // 获取玩家关联代理
        Long proxyId = frontUser.getProxyId();
        BackAgent backAgent = backAgentService.getById(proxyId);
        if (backAgent != null) {
            //获取代理等级
            Integer level = backAgent.getLevel();
            if (level == 1) {
                // 只有一层 计算一级代理的分成
                BigDecimal income = BigDecimal.valueOf(backAgent.getCommissionRate()).divide(new BigDecimal(100)).multiply(recharge.getRechargeAmount());
                recharge.setProxyOneId(proxyId);
                recharge.setProxyOneIncome(income);
                recharge.setPlatformIncome(recharge.getRechargeAmount().subtract(income));
            } else if (level == 2) {
                // 先计算二级代理的分成
                BigDecimal incomeLevel2 = BigDecimal.valueOf(backAgent.getCommissionRate()).divide(new BigDecimal(100)).multiply(recharge.getRechargeAmount());
                // 再获取一级代理信息
                BackAgent backAgentLevel1 = backAgentService.getById(backAgent.getParentId());
                // 计算一级代理的分成
                BigDecimal incomeLevel1 = BigDecimal.valueOf(backAgentLevel1.getCommissionRate()).divide(new BigDecimal(100)).multiply(recharge.getRechargeAmount());
                recharge.setProxyTwoId(proxyId);
                recharge.setProxyTwoIncome(incomeLevel2);
                recharge.setProxyOneId(backAgentLevel1.getId());
                recharge.setProxyOneIncome(incomeLevel1.subtract(incomeLevel2));
                recharge.setPlatformIncome(recharge.getRechargeAmount().subtract(incomeLevel1));
            } else if (level == 3) {
                // 先计算三级代理的分成
                BigDecimal incomeLevel3 = BigDecimal.valueOf(backAgent.getCommissionRate()).divide(new BigDecimal(100)).multiply(recharge.getRechargeAmount());
                // 再获取二级代理信息
                BackAgent backAgentLevel2 = backAgentService.getById(backAgent.getParentId());
                // 再计算二级代理的分成
                BigDecimal incomeLevel2 = BigDecimal.valueOf(backAgentLevel2.getCommissionRate()).divide(new BigDecimal(100)).multiply(recharge.getRechargeAmount());
                // 再获取一级代理信息
                BackAgent backAgentLevel1 = backAgentService.getById(backAgentLevel2.getParentId());
                // 计算一级代理的分成
                BigDecimal incomeLevel1 = BigDecimal.valueOf(backAgentLevel1.getCommissionRate()).divide(new BigDecimal(100)).multiply(recharge.getRechargeAmount());
                recharge.setProxyThreeId(proxyId);
                recharge.setProxyThreeIncome(incomeLevel3);
                recharge.setProxyTwoId(backAgentLevel2.getId());
                recharge.setProxyTwoIncome(incomeLevel2.subtract(incomeLevel3));
                recharge.setProxyOneId(backAgentLevel1.getId());
                recharge.setProxyOneIncome(incomeLevel1.subtract(incomeLevel2));
                recharge.setPlatformIncome(recharge.getRechargeAmount().subtract(incomeLevel1));
            }
        }
        return recharge;
    }
}

